package m6lock

import (
	"sync"
	"time"
	"fmt"
)

var wg sync.WaitGroup
var x int

//1. 并发安全和锁
func add() {
	for i := 0; i < 500000; i++ {
		x = x + 1
	}
	wg.Done()
}

func LockDemo1() {
	wg.Add(2)
	go add()
	go add()
	wg.Wait()
	time.Sleep(time.Second)
	fmt.Println(x)
}

//1.1.1. 互斥锁
var lock sync.Mutex
func addLock() {
	for i := 0; i < 500000; i++ {
		lock.Lock()
		x = x + 1
		lock.Unlock()
	}
	wg.Done()
}

func LockDemo2() {
	wg.Add(2)
	go addLock()
	go addLock()
	wg.Wait()
	time.Sleep(time.Second)
	fmt.Println(x)
}

// 1.1.2. 读写互斥锁
// 读写锁分为两种：读锁和写锁。当一个goroutine获取读锁之后，其他的goroutine如果是获取读锁会继续获得锁，
// 如果是获取写锁就会等待；当一个goroutine获取写锁之后，其他的goroutine无论是获取读锁还是写锁都会等待。
var rwlock sync.RWMutex

func write() {
	// lock.Lock()   // 加互斥锁
	rwlock.Lock() // 加写锁
	x = x + 1
	time.Sleep(10 * time.Millisecond) // 假设读操作耗时10毫秒
	rwlock.Unlock()                   // 解写锁
	// lock.Unlock()                     // 解互斥锁
	wg.Done()
}

func read() {
	// lock.Lock()                  // 加互斥锁
	rwlock.RLock()               // 加读锁
	time.Sleep(time.Millisecond) // 假设读操作耗时1毫秒
	rwlock.RUnlock()             // 解读锁
	// lock.Unlock()                // 解互斥锁
	wg.Done()
}

func LockDemo3() {
	start := time.Now()
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go write()
	}

	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go read()
	}

	wg.Wait()
	end := time.Now()
	fmt.Println(end.Sub(start))
}